#include <iostream>
#include <string>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/wait.h>
#include "Task.hpp"
#include "threadPool.hpp"
#include "Deamon.hpp"

uint16_t defaultport = -1;
std::string defaultip = "0.0.0.0";
const int backlog = 5;
class TcpServer;

struct ThreadData
{
    ThreadData(int sockfd, const std::string &ip, const uint16_t port, TcpServer *pts)
        : _sockfd(sockfd)
        ,_clientip(ip)
        , _clientport(port)
        , _pts(pts)
    {
    }

    int _sockfd;
    std::string _clientip;
    std::uint16_t _clientport;
    TcpServer *_pts;
};

class TcpServer
{
public:
    TcpServer(uint16_t port = defaultport, const std::string &ip = defaultip)
        : _port(port), _ip(ip)
    {
    }

    void Init()
    {
        _listensockfd = socket(AF_INET, SOCK_STREAM, 0);
        if (_listensockfd < 0)
        {
            perror("socket fail");
            exit(errno);
        }
        std::cout << "create socket success" << std::endl;

        struct sockaddr_in local;
        memset(&local, 0, sizeof(local));
        local.sin_port = htons(_port);
        local.sin_family = AF_INET;
        local.sin_addr.s_addr = inet_addr(_ip.c_str());
        // inet_aton(_ip.c_str(), &local.sin_addr);
        socklen_t len = sizeof(local);

        if (bind(_listensockfd, (sockaddr *)&local, len) < 0)
        {
            perror("bind fail");
            exit(-1);
        }
        std::cout << "bind success" << std::endl;

        // 监听
        if (listen(_listensockfd, backlog) < 0)
        {
            perror("listen fail");
            exit(errno);
        }
        std::cout << "listen begin..." << std::endl;
    }

    // static void *routine(void *argv)
    // {
    //     pthread_detach(pthread_self());

    //     ThreadData *ptd = (ThreadData *)argv;

    //     ptd->_pts->Service(ptd->_sockfd, ptd->_clientip, ptd->_clientport);
    //     close(ptd->_sockfd);
    //     return nullptr;
    // }

    void Run()
    {
        Deamon();
        std::cout << "Server Running..." << std::endl;
        ThreadPool<Task>::GetInstence(5)->start();
        while (true)
        {
            struct sockaddr_in client;
            socklen_t len = 0;
            int sockfd = accept(_listensockfd, (sockaddr *)&client, &len);
            std::cout << "get a new link..." << std::endl;

            uint16_t clientport = ntohs(client.sin_port);
            char ipstr[32];
            inet_ntop(AF_INET, &(client.sin_addr), ipstr, sizeof(ipstr));
            std::cout << "get a sockfd : " << sockfd << std::endl;

            printf("Get a New Link..., sockfd : %d, clientip: %s, clientport: %d\n", sockfd, ipstr, clientport);
            // 单进程
            // Service(sockfd, ipstr, clientport);
            // close(sockfd);

            // 多进程
            // pid_t id = fork();
            // if(id == 0)
            // {
            //     close(_listensockfd);
            //     if(fork() > 0) exit(0);
            //     Service(sockfd, ipstr, clientport);
            //     close(sockfd);
            //     exit(0);
            // }
            // close(sockfd);
            // waitpid(id, nullptr, 0);

            // 多线程
            // ThreadData *td = new ThreadData(sockfd, ipstr, clientport, this);
            // pthread_t tid;
            // pthread_create(&tid, nullptr, routine, (void *)td);

            // 线程池
            Task t(sockfd, ipstr, clientport);
            ThreadPool<Task>::GetInstence(5)->Push(t);
        }
    }

    // void Service(int sockfd, const std::string &clientip, const uint16_t clientport)
    // {
    //     char buffer[4096];
    //     while (true)
    //     {
    //         ssize_t n = read(sockfd, buffer, sizeof(buffer) - 1);
    //         if (n > 0)
    //         {
    //             buffer[n] = 0;
    //             std::cout << "client Say# " << buffer << std::endl;
    //             std::string echo_string = "TcpServer say# ";
    //             echo_string += buffer;

    //             write(sockfd, echo_string.c_str(), echo_string.size());
    //         }
    //         else if (n == 0)
    //         {
    //             std::cout << "Server Quit...." << std::endl;
    //             break;
    //         }
    //     }
    // }

    ~TcpServer()
    {
    }

private:
    int _listensockfd;
    uint16_t _port;
    std::string _ip;
};